# coding:utf-8
# Car管理

import traceback, uuid
from sqlalchemy import and_, or_
import glog, gdb
from car import *
from db_tables import *

GARAGE_W = 8
GARAGE_H = 4


def _pack(d): return repr(d)
def _unpack(d): return eval(d)


# { role_id : {car_id1 : car1, ..}, .. }
data = {}

def init ():
    pass


# 取得道具
def get (owner, car_id):
    cars = _get_owner_data(owner)
    if car_id not in cars:
        glog.error("car_mgr>get, no this id, owner:%s, id:%s" % (owner,car_id))
        return None
    return cars[car_id]


# 获得全部
def get_cars_by_owner (owner):
    cars = _get_owner_data(owner)
    return cars.values()


def _get_empty_pos (owner):
    data = _get_owner_data(owner)
    
    for y in xrange(GARAGE_H):
        for x in xrange(GARAGE_W):
            car = _get_car_by_pos(data, x, y)
            if car is None:
                return [x, y]
    return None


# 增加道具
def add (owner, car_type):
    pos = _get_empty_pos(owner)
    if pos is None:
        glog.error('car_mgr>add car FAILED, no empty position, type:%s' % car_type)
        return False

    car = Car()
    car.id = uuid.uuid1().hex   # 道具ID
    car.owner = owner
    car.type = car_type
    car.pos = pos
    car.hp = 100 #* from
    car.mhp = 100
    data[owner][car.id] = car

    if not save_owner_data(owner):
        glog.error('car_mgr>add car FAILED, write db error, type:%s' % car_type)
        data[owner].pop(car.id)
        return False
    return True


# 减少道具
def remove (owner, car_id):
    role_data = _get_owner_data(owner)
    car = _get_car_by_id(role_data, car_id)
    if car is None:
        glog.error('car_mgr>remove FAILED, no this id:%s' % car_id)
        return False

    role_data.pop(car.id)
    return save_owner_data(owner)


def _get_car_by_pos (owner_data, x, y):
    for id, car in owner_data.iteritems():
        if car.pos[0] == x and car.pos[1] == y: return car
    return None


def _get_car_by_id (owner_data, id):
    return owner_data.get(id, None)

# --------------------------------------------------------
def _get_owner_data (owner): 
    if owner not in data:
        cars = _load_db(owner)
        data[owner] = cars
    return data[owner]


def save_owner_data (owner):
    res = _save_db(owner, _get_owner_data(owner))
    if not res:
        glog.error('car_mgr>save_owner_data FAILED, owner:%s' % owner) 
    return res
    

# 从数据库中加载数据
def _load_db (owner):
    role_data = _unpack( db_get_data(owner) )
    
    cars = {}
    for id, adata in role_data.iteritems():
        car = Car()
        car.id = id
        car.from_dictionary(adata)
        cars[car.id] = car

    #glog.log("car_mgr>_load_db, owner:%s" % owner)
    return cars


def _save_db (owner, data):
    role_data = {}
    for id, adata in data.iteritems():
        role_data[id] = adata.to_dictionary()

    return db_set_data( owner, _pack(role_data) )


# ------------------------------------------------------
def db_get_data (owner):
    ses = gdb.get_session()
    res = ses.query(DBCar).filter_by(id=owner).all() # only one
    if len(res) > 0:
        return res[0].data
    else:
        return "{}"

def db_set_data (owner, data):
    ses = gdb.get_session()
        
    res = ses.query(DBCar).filter_by(id=owner).all()
    if len(res) > 0:
        # update
        try:
            record = res[0]
            record.data = data
            ses.commit()
            return True
        except Exception, e:
            print traceback.format_exc()
            ses.rollback()
            return False
    else:
        # insert
        try:
            ses.add(DBCar(owner, data))
            ses.commit()
            return True
        except Exception, e:
            print traceback.format_exc()
            ses.rollback()
            return False